package com.example.demozy.controller;

import com.example.demozy.api.CommonResult;
import com.example.demozy.entity.*;
import com.example.demozy.service.ConditionSheetCommodityService;
import com.example.demozy.service.ConditionSheetService;
import com.example.demozy.service.StockService;
import com.example.demozy.vo.BackTestResultVO;
import com.example.demozy.vo.SingleBackTestResultVO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;

import java.text.DecimalFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.List;

/**
 * @author 张展鹏
 */
@RestController
public class ConditionSheetController {
    // **************** 公开变量

    // **************** 私有变量

    @Autowired
    private ConditionSheetService conditionSheetService;
    @Autowired
    private StockService stockService;
    @Autowired
    private ConditionSheetCommodityService conditionSheetCommodityService;

    // **************** 继承方法

    // **************** 公开方法

    /**
     * 获得条件单库
     * TODO 还有一部分商城的
     * @param user : 得到JSON字符串中的值user
     */
    @PostMapping(value = "/conditionSheetWarehouse")
    public CommonResult getConditionSheetWarehouse(@RequestBody User user) {
        List<ConditionSheet> list1 = conditionSheetService.listAllOrderConditionSheets(String.valueOf(user.getUserId()));
        List<ConditionSheet> list2 = conditionSheetService.listAllConditionSheets(String.valueOf(user.getUserId()));
        list1.addAll(list2);
        return CommonResult.success(list1);
    }

    /**
     * 获得指定未上架的条件单的所有条件及其参数
     * @param conditionSheet : 得到JSON字符串中的值conditionSheet
     */
    @PostMapping(value = "/offConditionSheetDetail")
    public CommonResult getOffConditionSheetDetail(@RequestBody
            ConditionSheet conditionSheet) {
        ArrayList<SheetCondition> sheetList =
                (ArrayList<SheetCondition>) conditionSheetService.listConditionSheetsConditions(conditionSheet.getConditionSheetId());
        for (SheetCondition sheet: sheetList) {
            if (sheet.getOrderType().equals("0")){
                sheet.setOrderType("买入");
            }else if (sheet.getOrderType().equals("1")){
                sheet.setOrderType("卖出");
            }
        }
        return CommonResult.success(sheetList);
    }

    /**
     * 更新指定条件单的名称
     *
     * @param conditionSheet : 得到JSON字符串中的值conditionSheet
     */
    @PostMapping(value = "/updateConditionSheetName")
    public CommonResult updateConditionSheetName(@RequestBody ConditionSheet conditionSheet) {
        return CommonResult.success(conditionSheetService.updateConditionSheetName(conditionSheet.getConditionSheetId(), conditionSheet.getConditionSheetName()));
    }

    /**
     * 插入条件单的条件
     *
     * @param conditionSheet : 得到JSON字符串中的值conditionSheet
     */
    @PostMapping(value = "/insertConditionSheet")
    public CommonResult insertConditionSheet(@RequestBody ConditionSheet conditionSheet) {
        String conditionSheetId = String.valueOf(conditionSheetService.getMaxConditionSheetId() + 1);
        String conditionSheetName = conditionSheet.getConditionSheetName();
        String authorId = conditionSheet.getAuthorId();
        ArrayList<SheetCondition> conditions = conditionSheet.getConditions();
        conditionSheetService.insertConditionSheet(conditionSheetId,conditionSheetName,authorId);
        for (SheetCondition condition : conditions){
            String conditionId = condition.getConditionId();
            String conditionParameter = condition.getConditionParameter();
            String order = condition.getOrderType();
            int orderType = 0;
            if (order.equals("买入")){
                orderType = 0;
            }else if (order.equals("卖出")){
                orderType = 1;
            }
            conditionSheetService.insertSheetCondition(conditionSheetId, conditionId, conditionParameter, orderType);
        }
        if (String.valueOf(conditionSheetService.getMaxConditionSheetId()).equals(conditionSheetId)){
            return CommonResult.success(null);
        }else {
            return CommonResult.failed("新建条件单失败");
        }
    }

    /**
     * 更新指定条件单的名称
     *
     * @param conditionSheet : 得到JSON字符串中的值conditionSheet
     */
    @PostMapping(value = "/deleteConditionSheet")
    public CommonResult deleteConditionSheet(@RequestBody ConditionSheet conditionSheet) {
        return CommonResult.success(conditionSheetService.deleteConditionSheet(conditionSheet.getConditionSheetId()));
    }

    /**
     * 回测条件单
     *
     * @param backTestReport : 得到JSON字符串中的值backTestReport
     */
    @PostMapping(value = "/backTest")
    public CommonResult backTest(@RequestBody BackTestReport backTestReport)
            throws ParseException {
        /**
         * 获取条件单参数。
         */
        ArrayList<SheetCondition> sheetList =
                (ArrayList<SheetCondition>) conditionSheetService.listConditionSheetsConditions(backTestReport.getConditionSheetId());
        ArrayList<SheetCondition> conditions = new ArrayList();
        double buyPosition = 0;
        double sellPosition = 0;
        for (int i = 0; i < sheetList.size(); i++){
            if (!sheetList.get(i).getConditionId().equals("4")){
                conditions.add(sheetList.get(i));
            }else {
                if (sheetList.get(i).getOrderType().equals("0")){
                    buyPosition = Double.parseDouble(sheetList.get(i).getConditionParameter());
                }else if (sheetList.get(i).getOrderType().equals("1")){
                    sellPosition = Double.parseDouble(sheetList.get(i).getConditionParameter());
                }
            }
        }
        if (conditions.size() == 0){
            return CommonResult.failed("无条件单参数");
        }

        List<HistoryModel> historyModels = stockService.getStockByCode(backTestReport.getBackTestStock());
        int startFlag = 0;
        int endFlag = 0;
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        for (int i = 0; i < historyModels.size(); i++){
            if (format.parse(historyModels.get(i).day).before(backTestReport.getStartTime()) &&
                    format.parse(historyModels.get(i+1).day).after(backTestReport.getStartTime())){
                startFlag = i + 1;
            }
            if (format.parse(historyModels.get(i).day).before(backTestReport.getEndTime()) &&
                    format.parse(historyModels.get(i+1).day).after(backTestReport.getEndTime())){
                endFlag = i + 1;
                break;
            }
        }
        historyModels = historyModels.subList(startFlag, endFlag);

        /**
         * 默认条件单正向突破卖，逆向突破买。
         */
        int backTestType = 0;
        //资金
        double property = 0;
        //资金
        double initialCapital = 100000;
        double capital = 100000;
        //股数
        int share = 0;
        //逆向突破点
        double buyPrice = 0;
        //正向突破点
        double sellPrice = 0;
        if (conditions.size() == 1){
            if (conditions.get(0).getConditionId().equals("1") && conditions.get(0).getOrderType().equals("1")){
                backTestType = 1;
                sellPrice = Double.parseDouble(conditions.get(0).getConditionParameter());
            }else if (conditions.get(0).getConditionId().equals("2") && conditions.get(0).getOrderType().equals("0")){
                backTestType = 1;
                buyPrice = Double.parseDouble(conditions.get(0).getConditionParameter());
            }else if (conditions.get(0).getConditionId().equals("1") && conditions.get(0).getOrderType().equals("0")){
                backTestType = 2;
                buyPrice = Double.parseDouble(conditions.get(0).getConditionParameter());
            }else if (conditions.get(0).getConditionId().equals("2") && conditions.get(0).getOrderType().equals("1")){
                backTestType = 2;
                sellPrice = Double.parseDouble(conditions.get(0).getConditionParameter());
            }else {
                return CommonResult.failed("条件单参数错误");
            }
        }else {
            for (int i = 0; i < conditions.size(); i++){
                if (conditions.get(i).getConditionId().equals("1") && conditions.get(i).getOrderType().equals("1")){
                    backTestType = 1;
                    sellPrice = Double.parseDouble(conditions.get(i).getConditionParameter());
                }else if (conditions.get(i).getConditionId().equals("2") && conditions.get(i).getOrderType().equals("0")){
                    backTestType = 1;
                    buyPrice = Double.parseDouble(conditions.get(i).getConditionParameter());
                }else if (conditions.get(i).getConditionId().equals("1") && conditions.get(i).getOrderType().equals("0")){
                    backTestType = 2;
                    buyPrice = Double.parseDouble(conditions.get(i).getConditionParameter());
                }else if (conditions.get(i).getConditionId().equals("2") && conditions.get(i).getOrderType().equals("1")){
                    backTestType = 2;
                    sellPrice = Double.parseDouble(conditions.get(i).getConditionParameter());
                }else {
                    return CommonResult.failed("条件单参数错误");
                }
            }
        }
        buyPosition = buyPosition / 100;
        sellPosition = sellPosition / 100;
        BackTestResultVO backTestResult = new BackTestResultVO();

        switch (backTestType){
            case 0:
                return CommonResult.failed("回测方法未定义");
            case 1:
                for (int i = 0; i < historyModels.size(); i++){
                    SingleBackTestResultVO singleBackTestResult = new SingleBackTestResultVO();
                    singleBackTestResult.setDay(format.parse(historyModels.get(i).day));
                    singleBackTestResult.setOpen(Double.parseDouble(historyModels.get(i).open));
                    singleBackTestResult.setHigh(Double.parseDouble(historyModels.get(i).high));
                    singleBackTestResult.setLow(Double.parseDouble(historyModels.get(i).low));
                    singleBackTestResult.setClose(Double.parseDouble(historyModels.get(i).close));
                    double price = Double.parseDouble(historyModels.get(i).close);
                    property = capital + share * price;
                    if (capital > 0){
                        singleBackTestResult.setTransactionPrice(price);
                        if (price >= buyPrice){
                            property = capital + share * price;
                            int buyShare = 0;
                            if ((property * buyPosition) <= capital){
                                buyShare = (int) Math.floor(property * buyPosition / price);
                                share = share + buyShare;
                            }else {
                                if (capital > price){
                                    buyShare = (int) Math.floor(capital / price);
                                    share = share + buyShare;
                                }
                            }
                            capital = capital - buyShare * price;
                            singleBackTestResult.setBuyShare(buyShare);
                        }
                    }
                    if (share > 0){
                        singleBackTestResult.setTransactionPrice(price);
                        if (price <= sellPrice){
                            property = capital + share * price;
                            int sellShare = (int) Math.floor(property * sellPosition / price);
                            if (sellShare <= share){
                                share = share - sellShare;
                                capital = capital + sellShare * price;
                            }else {
                                capital = capital + share * price;
                                share = 0;
                            }
                            singleBackTestResult.setSellShare(sellShare);
                        }
                    }
                    singleBackTestResult.setShare(share);
                    singleBackTestResult.setCapital(capital);
                    singleBackTestResult.setProperty(property);
                    backTestResult.addSingleBackTestResultVO(singleBackTestResult);
                }
                break;
            case 2:
                for (int i = 0; i < historyModels.size(); i++){
                    SingleBackTestResultVO singleBackTestResult = new SingleBackTestResultVO();
                    singleBackTestResult.setDay(format.parse(historyModels.get(i).day));
                    singleBackTestResult.setOpen(Double.parseDouble(historyModels.get(i).open));
                    singleBackTestResult.setHigh(Double.parseDouble(historyModels.get(i).high));
                    singleBackTestResult.setLow(Double.parseDouble(historyModels.get(i).low));
                    singleBackTestResult.setClose(Double.parseDouble(historyModels.get(i).close));
                    double price = Double.parseDouble(historyModels.get(i).close);
                    property = capital + share * price;
                    if (capital > 0){
                        singleBackTestResult.setTransactionPrice(price);
                        if (price <= buyPrice){
                            property = capital + share * price;
                            int buyShare = 0;
                            if ((property * buyPosition) <= capital){
                                buyShare = (int) Math.floor(property * buyPosition / price);
                                share = share + buyShare;
                            }else {
                                if (capital > price){
                                    buyShare = (int) Math.floor(capital / price);
                                    share = share + buyShare;
                                }
                            }
                            capital = capital - buyShare * price;
                            singleBackTestResult.setBuyShare(buyShare);
                        }
                    }
                    if (share > 0){
                        singleBackTestResult.setTransactionPrice(price);
                        if (price >= sellPrice){
                            property = capital + share * price;
                            int sellShare = (int) Math.floor(property * sellPosition / price);
                            if (sellShare <= share){
                                share = share - sellShare;
                                capital = capital + sellShare * price;
                            }else {
                                capital = capital + share * price;
                                share = 0;
                            }
                            singleBackTestResult.setSellShare(sellShare);
                        }
                    }
                    singleBackTestResult.setShare(share);
                    singleBackTestResult.setCapital(capital);
                    singleBackTestResult.setProperty(property);
                    backTestResult.addSingleBackTestResultVO(singleBackTestResult);
                }
                break;
        }

        double price = Double.parseDouble(historyModels.get(historyModels.size() - 1).close);
        property = capital + share * price;
        DecimalFormat df = new DecimalFormat("#.00");
        double yield = Double.parseDouble(df.format((double) property / initialCapital)) - 1;

        backTestResult.setInitialCapital(initialCapital);
        backTestResult.setCapital(capital);
        backTestResult.setProperty(property);
        backTestResult.setShare(share);
        backTestResult.setTransactionPrice(price);
        backTestResult.setYield(yield);

        return CommonResult.success(backTestResult);
    }

    /**
     * 上架审核申请
     *
     * @param commodityCheck : 得到JSON字符串中的值commodityCheck
     */
    @PostMapping(value = "/checkConditionSheet")
    public CommonResult updateConditionSheetOnState(@RequestBody CommodityCheck commodityCheck) {
        int state = conditionSheetService.getConditionSheetOnState(commodityCheck.getConditionSheetId());
        if (state == 0){
            conditionSheetService.updateConditionSheetOnState(commodityCheck.getConditionSheetId(), 2);
            return CommonResult.success(conditionSheetCommodityService.insertConditionSheetCommodityCheck(commodityCheck.getConditionSheetId(), commodityCheck.getCommodityName()
                    , 2, commodityCheck.getCommodityDescription(), commodityCheck.getCommodityPrice(), commodityCheck.getAuthorId()));
        }else if (state == 1){
            return CommonResult.failed("条件单已上架");
        }else if (state == 2){
            return CommonResult.failed("条件单在审核中");
        }
        return CommonResult.failed("参数错误");
    }

    /**
     * 插入回测报告表。
     *
     * @param backTestReport : 得到JSON字符串中的值backTestReport
     */
    @PostMapping(value = "/saveBackTestReport")
    public CommonResult saveBackTestReport(@RequestBody BackTestReport backTestReport) {
        //SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        return CommonResult.success(conditionSheetService.saveBackTestReport(backTestReport.getConditionSheetId(), backTestReport.getBackTestStock()
        , backTestReport.getStartTime(), backTestReport.getEndTime(), backTestReport.getBackTestYield()));
    }

    // **************** 私有方法

}
